package ml.kupin.order.service.impl;

import com.alibaba.fastjson.JSON;
import ml.kupin.common.constant.KuPinConstant;
import ml.kupin.common.jedis.JedisClient;
import ml.kupin.common.utils.DateUtils;
import ml.kupin.common.utils.KuPinResult;
import ml.kupin.mapper.TbOrderItemMapper;
import ml.kupin.mapper.TbOrderMapper;
import ml.kupin.mapper.TbOrderShippingMapper;
import ml.kupin.order.pojo.DetailedOrder;
import ml.kupin.order.service.OrderService;
import ml.kupin.pojo.TbOrder;
import ml.kupin.pojo.TbOrderExample;
import ml.kupin.pojo.TbOrderItem;
import ml.kupin.pojo.TbOrderShipping;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by 小柯(Allen Kerr) on 17.5.8 18:50.
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private JedisClient jedisClient;

    @Autowired
    private TbOrderMapper orderMapper;

    @Autowired
    private TbOrderItemMapper orderItemMapper;

    @Autowired
    private TbOrderShippingMapper orderShippingMapper;

    @Value("${order_id_redis}")
    private String order_id_redis;

    @Value("${order_id_start}")
    private String order_id_start;

    @Value("${order_item_id_redis}")
    private String order_item_id_redis;

    @Value("${order_not_pay_prefix}")
    private String order_not_pay_prefix;

    @Value("${order_not_pay_lifetime}")
    private int order_not_pay_lifetime;

    /**
     * 创建订单，需要向三张表中插入数据
     *
     * @param detailedOrder
     * @return
     */
    @Override
    public KuPinResult createOrder(DetailedOrder detailedOrder) {
        //1、接收表单的数据 detailedOrder
        //2、向订单表插入数据
        /**
         * order_id           订单id
         * payment            实付金额，精确到2位小数，单位:元
         * payment_type       支付类型，1、在线支付，2、货到付款
         * post_fee           邮费，精确到2位小数，单位:元
         * status             状态：1、未付款，2、已付款，3、未发货，4、已发货，5、交易成功，6、交易关闭
         * create_time        订单创建时间
         * update_time        订单更新时间
         * payment_time       付款时间
         * consign_time       发货时间
         * end_time           交易完成时间
         * close_time         交易关闭时间
         * hipping_name       物流名称
         * hipping_code       物流单号
         * user_id            用户id
         * buyer_message      买家留言
         * buyer_nick         买家昵称
         * buyer_rate         买家是否已经评价
         */
        //生成订单id，要求订单号不能重复，订单号可读性号。
        //可以使用 redis 的 incr 命令生成订单号，订单号需要一个初始值。
        if (!jedisClient.exists(order_id_redis)) {
            jedisClient.set(order_id_redis, order_id_start);
        }
        String orderId = jedisClient.incr(order_id_redis).toString();
        detailedOrder.setOrderId(orderId);
        //表单数据：payment, paymentType, postType
        //已补全数据：user_id, buyer_nick
        //补全数据：status, create_time, update_time
        detailedOrder.setStatus(KuPinConstant.Order_Not_Pay);
        Date createTime = new Date();
        detailedOrder.setCreateTime(createTime);
        detailedOrder.setUpdateTime(createTime);
        //其他字段 null
        //执行插入操作
        orderMapper.insertSelective(detailedOrder);

        //4、向订单明细表插入数据
        /**
         * id            订单明细id
         * item_id       商品id
         * order_id      订单id
         * num           商品购买数量
         * title         商品标题
         * price         商品单价
         * total_fee     商品总金额
         * pic_path      商品图片地址
         */
        List<TbOrderItem> orderItems = detailedOrder.getOrderItems();
        for (TbOrderItem orderItem : orderItems) {
            //表单数据：item_id, num, title, price, total_fee, pic_path
            //补全属性：id, order_id
            orderItem.setId(jedisClient.incr(order_item_id_redis).toString());
            orderItem.setOrderId(orderId);
            //执行插入操作
            orderItemMapper.insertSelective(orderItem);
        }
        //5、向订单物流表插入数据
        /**
         * order_id               订单ID
         * receiver_name          收货人全名
         * receiver_phone         固定电话
         * receiver_mobile        移动电话
         * receiver_state         省份
         * receiver_city          城市
         * receiver_district      区/县
         * receiver_address       收货地址，如：xx路xx号
         * receiver_zip           邮政编码,如：310001
         * created                创建时间
         * updated                修改时间
         */
        //表单数据：receiver_name, receiver_mobile, receiver_state, receiver_city, receiver_district, receiver_address
        //补全属性：order_id, created, updated
        TbOrderShipping orderShipping = detailedOrder.getOrderShipping();
        orderShipping.setOrderId(orderId);
        orderShipping.setCreated(createTime);
        orderShipping.setUpdated(createTime);
        //执行插入操作
        orderShippingMapper.insertSelective(orderShipping);

        //=====================将订单放入redis中，设置生存时间========================
        TbOrder orderInfo = detailedOrder;
        jedisClient.set(order_not_pay_prefix + orderId, JSON.toJSONString(orderInfo));
        jedisClient.expire(order_not_pay_prefix + orderId, order_not_pay_lifetime);
        //=====================将订单放入redis中，设置生存时间========================

        //6、返回结果
        return KuPinResult.ok(orderId);
    }

    /**
     * 为订单支付页面查询订单数据，
     * 如果redis中已找到，订单即为未支付状态；
     * 如果redis中没有找到，再去数据库中查，判断订单状态；
     * 如果数据库中也为找到，那最终返回404页面
     *
     * @param orderId
     * @return
     */
    @Override
    public KuPinResult getOrderInfo(String orderId) {
        //如果redis中已找到，订单即为未支付状态
        if (jedisClient.exists(order_not_pay_prefix + orderId)) {
            String json_order = jedisClient.get(order_not_pay_prefix + orderId);
            TbOrder orderInfo = JSON.parseObject(json_order, TbOrder.class);
            Long orderTtl = jedisClient.ttl(order_not_pay_prefix + orderId);
            Map<String, Object> data = new HashMap<>();
            data.put("orderInfo", orderInfo);
            data.put("orderTtl", orderTtl);
            return KuPinResult.ok(data);
        }

        //如果redis中没有找到，再去数据库中查，判断订单状态
        TbOrder orderInfo = orderMapper.selectByPrimaryKey(orderId);
        if (orderInfo != null) {
            String msg = null;
            switch (orderInfo.getStatus()) {
                case KuPinConstant.Order_Not_Pay:
                    //redis中未找到且DB中仍为未支付状态，那么肯定是超时未支付
                    // ——> quartz的任务还未执行，就被查询出来了
                    //所以此处应该调用方法将状态改为已关闭
                    updateStatus(orderId, KuPinConstant.Order_Closed, KuPinConstant.Order_Not_Pay,
                            DateUtils.getTimeAgo(order_not_pay_lifetime));
                    msg = "超时未支付，已关闭";
                    break;
                case KuPinConstant.Order_Payed:
                    msg = "已支付";
                    break;
                case KuPinConstant.Order_Not_Post:
                    msg = "已支付，即将发货";
                    break;
                case KuPinConstant.Order_Posted:
                    msg = "已收货";
                    break;
                case KuPinConstant.Order_Success:
                    msg = "已完成";
                    break;
                case KuPinConstant.Order_Closed:
                    msg = "超时未支付，已关闭";
                    break;
            }
            return KuPinResult.notOk(msg, orderInfo);
        }

        //如果数据库中也为找到，那最终返回404页面
        return null;
    }

    /**
     * 更新订单状态
     *
     * @param status
     * @return
     */
    @Override
    public KuPinResult updateStatus(String orderId, int status, int originalStatus, Date createTimeLessThan) {
        //改之后的状态
        TbOrder order = new TbOrder();
        if (StringUtils.isNotBlank(orderId)) {
            order.setOrderId(orderId);
        }
        order.setStatus(status);
        order.setUpdateTime(new Date());
        //修改条件
        TbOrderExample orderExample = new TbOrderExample();
        TbOrderExample.Criteria criteria = orderExample.createCriteria();
        criteria.andStatusEqualTo(originalStatus);
        criteria.andCreateTimeLessThan(createTimeLessThan);
        //执行修改
        int updateCount = orderMapper.updateByExampleSelective(order, orderExample);
        if (updateCount > 0) {
            return KuPinResult.ok(updateCount);
        }
        return KuPinResult.notOk(updateCount);
    }

    /*@Override
    public KuPinResult updateNotPayOrderStatus() {
        //改动
        TbOrder order = new TbOrder();
        order.setStatus(KuPinConstant.Order_Closed);
        order.setUpdateTime(new Date());
        //条件
        TbOrderExample orderExample = new TbOrderExample();
        TbOrderExample.Criteria criteria = orderExample.createCriteria();
        criteria.andCreateTimeLessThan(DateUtils.getTimeAgo(order_not_pay_lifetime));
        criteria.andStatusEqualTo(KuPinConstant.Order_Not_Pay);
        //执行
        int updateCount = orderMapper.updateByExampleSelective(order, orderExample);
        if (updateCount > 0) {
            return KuPinResult.ok(updateCount);
        }
        return KuPinResult.notOk(updateCount);
    }*/

}
